package com.ycy.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;

public class NewIO2 {

  public static void main(String[] args) {

    NewIO2 newIO2 = new NewIO2();
    newIO2.initServer();

  }


  public void initServer() {

    try {
      ServerSocketChannel serverChannel = ServerSocketChannel.open();
      serverChannel.bind(new InetSocketAddress(8090));
      //非阻塞
      serverChannel.configureBlocking(false);

      // selector select poll  。。。
      // 或者 epoll 中的 epoll_create 开辟一个空间
      Selector selector = Selector.open();

      // select,poll:jvm 里面开辟一个数组 文件描述符 放进去
      // epoll epoll_ctl (create的空间，add，，accept)；
      serverChannel.register(selector, SelectionKey.OP_ACCEPT);

      //服务器启动了
      System.out.println("服务启动了。。。");

      // select,poll 内核中 select(fd) poll(fd)
      // epoll epoll_wait

      while (true) {
        selector.select();
        System.out.println("获取监听");
        Set<SelectionKey> keyss = selector.selectedKeys();
        Iterator<SelectionKey> keyIterator = keyss.iterator();
        while (keyIterator.hasNext()) {
          SelectionKey key = keyIterator.next();

          // 不移除 会重新循环遍历，监听过的就丢弃即可
          keyIterator.remove();

          if (key.isAcceptable()) {
            // accept 建立连接
            AcceptHanlder(key, serverChannel, selector);
          } else if (key.isReadable()) {

            // 读取准备好的io
            readHandler(key, serverChannel, selector);
          }  else {
            //为什么 监听不到 要关闭
            key.cancel();

          }

        }

      }


    } catch (IOException e) {
      e.printStackTrace();
    }

  }

  private void readHandler(SelectionKey key, ServerSocketChannel serverChannel, Selector selector) {
    SelectableChannel channel = key.channel();

    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

    SocketChannel socketChannel = (SocketChannel) channel;

    try {
      int read = socketChannel.read(byteBuffer);
      if (read <= 0){
        // 为什么  这里要关闭连接 ，大概是因为客服端主动断开了连接
        System.out.println("客服端主动断开了连接");
        socketChannel.close();
      }
      byteBuffer.flip();
      byte[] aaa = new byte[byteBuffer.limit()];
      // 把buffer赋值给数组
      byteBuffer.get(aaa);
      System.out.println(new String(aaa));
    } catch (IOException e) {
      e.printStackTrace();
      try {
        socketChannel.close();
      } catch (IOException ex) {
        ex.printStackTrace();
      }
    } finally {
//      try {
//        socketChannel.close();
//      } catch (IOException e) {
//        e.printStackTrace();
//      }
    }


  }

  private void AcceptHanlder(SelectionKey key, ServerSocketChannel server, Selector selector) throws IOException {
//    SelectableChannel channel = key.channel();
//    ServerSocketChannel clientChannel = (ServerSocketChannel) channel;
////    clientChannel.setOption()
//    SocketChannel client = clientChannel.accept();
//    client.configureBlocking(false);
//
////    ByteBuffer allocate = ByteBuffer.allocate(1024);
//    // select poll 把accept 获取到的文件描述符 放到用户态 jvm数组中
//    // epoll  调用epoll_ctl(fd3,add,fd7,event);
//    client.register(selector, SelectionKey.OP_READ);

    ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
    SocketChannel channel = serverChannel.accept();//接受连接请求
    channel.configureBlocking(false);
    channel.register(selector, SelectionKey.OP_READ);

    System.out.println("新客服端建立了连接 " + channel.getRemoteAddress());
  }

  public void start() {

    initServer();

  }

  public void channel() {

  }

}
